#pragma once

#include <occmesh/api/chart.h>

/**
 * @file ARAPBuilder.h
 * @author xingyifan
 * @date 2023-08-17 14:53
 *
 * @description: ARAP 构建器
 */

class ARAPBuilder
{
  private:
    struct HalfedgeData
    {
        double cot;
        MatrixXx1 dx;

        HalfedgeData() : cot(0)
        {
            dx.resize(2);
        }
    };

    Mesh *m_mesh;
    const std::vector<Chart> &m_charts;

    // 加权，确保矩阵非奇异
    double m_lambda;

    // 保存预分解的配置矩阵
    Eigen::SimplicialLDLT<SparseMatrix> m_solver;

    // 句柄，用于增加属性值
    OpenMesh::HPropHandleT<HalfedgeData> m_halfedgeData;
    OpenMesh::FPropHandleT<MatrixX> m_Lts;
    OpenMesh::FPropHandleT<int> m_chartIds;
    OpenMesh::VPropHandleT<int> m_ids;

  public:
    ARAPBuilder(Mesh *mesh, const std::vector<Chart> &charts, double lambda);
    ~ARAPBuilder();

    void Build(int times);

  private:
    SparseMatrix initializeData(const Chart &chart);
    void localPhase(const Chart &chart);
    void globalPhase(const Chart &chart, const SparseMatrix &M);
    void storeUVs(const Chart &chart);
};
